//
// Create by Zeng Yun on 2018/12/31
//

package home

import (
	"adai.design/jarvis/common/log"
	"adai.design/jarvis/home/model"
	"adai.design/jarvis/member"
	"time"
)

type AutomationManager struct {
	automations []*model.Automation
	// 定时器
	ticker chan time.Time
}

func (am *AutomationManager) set(automations []*model.Automation) {
	am.automations = automations
	for _, automation := range am.automations {
		automation.Load()
	}
	if am.ticker == nil {
		am.ticker = make(chan time.Time, 1)
		go func(ticker chan time.Time) {
			for {
				now := time.Now()
				duration := int(time.Second)*(60-now.Second()) - now.Nanosecond()
				select {
				case <-time.After(time.Duration(duration)):
					now = time.Now()
					ticker <- now
				}
			}
		}(am.ticker)
	}
}

func (am *AutomationManager) checkCondition(h *Home, a *model.Automation) bool {
	result := true
	for _, condition := range a.Conditions {
		switch condition.Type {
		case model.ConditionTypeTimePeriod:
			if event, ok := condition.Data.(*model.ConditionPeriod); ok {
				result = event.Check(time.Now())
			}

		case model.ConditionTypeLocation:
			if event, ok := condition.Data.(*model.ConditionLocation); ok {
				result = event.Check(h.memberManager.members)
			}
		}
		if result == false {
			return false
		}
	}
	return result
}

func (am *AutomationManager) checkAutomationTimerTrigger(h *Home, a *model.Automation, now time.Time) {
	var eventTimer *model.EventTimer
	for _, event := range a.Events {
		if event.Type == model.AutoTypeTimer {
			if tm, ok := event.Data.(*model.EventTimer); ok {
				if tm.Check(now) == true {
					eventTimer = tm
					break
				}
			}
		}
	}

	if eventTimer == nil {
		return
	}

	// 检查自动化执行条件
	if am.checkCondition(h, a) == false {
		return
	}

	// 执行场景
	var err1 error
	for _, scene := range a.Scenes {
		err1 = h.sceneManager.execute(h, scene)
	}

	// 执行动作
	var err2 error
	if a.Actions != nil && len(a.Actions) != 0 {
		err2 = h.containerManager.executeActions(h, a.Actions...)
	}

	if err1 != nil || err2 != nil {
		notify := &member.APNSAlert{
			Title: eventTimer.Title(),
			Body:  "自动化执行失败",
		}
		h.pushNotificationToMembers(notify)
	} else {
		notify := &member.APNSAlert{
			Title: eventTimer.Title(),
			Body:  a.SubTitle,
		}
		h.pushNotificationToMembers(notify)
	}
}

func (am *AutomationManager) checkMemberPositionTrigger(h *Home, a *model.Automation, m *model.Member) {
	var eventLocation *model.EventLocation
	for _, event := range a.Events {
		if event.Type == model.AutoTypeLocation {
			if el, ok := event.Data.(*model.EventLocation); ok {
				if el.Check(m, h.memberManager.members) == true {
					eventLocation = el
				}
			}
		}
	}

	if eventLocation == nil {
		return
	}

	if am.checkCondition(h, a) == false {
		return
	}

	// 执行场景
	var err1 error
	for _, scene := range a.Scenes {
		log.Info("scene: %s", scene)
		err1 = h.sceneManager.execute(h, scene)
	}

	// 执行动作
	var err2 error
	if a.Actions != nil && len(a.Actions) != 0 {
		err2 = h.containerManager.executeActions(h, a.Actions...)
	}

	mName := ""
	account, err := member.FindAccountById(m.Id)
	if err == nil {
		mName = account.Name
	}

	if err1 != nil || err2 != nil {
		notify := &member.APNSAlert{
			Title: eventLocation.Title(mName, h.instance.Name),
			Body:  "自动化执行失败",
		}
		h.pushNotificationToMembers(notify)
	} else {
		notify := &member.APNSAlert{
			Title: eventLocation.Title(mName, h.instance.Name),
			Body:  a.SubTitle,
		}
		h.pushNotificationToMembers(notify)
	}

}

// 检查定时自动化
func (am *AutomationManager) checkTimerTrigger(h *Home, now time.Time) {
	log.Debug("time now(%v)", now.Format("2006/01/02 15:04:05.9999"))
	for _, a := range am.automations {
		if a.IsEnable == true {
			am.checkAutomationTimerTrigger(h, a, now)
		}
	}
}

// 检查位置自动化
func (am *AutomationManager) checkPositionTrigger(h *Home, member *model.Member) {
	for _, a := range am.automations {
		if a.IsEnable == true {
			am.checkMemberPositionTrigger(h, a, member)
		}
	}
}
